//
//  main.m
//  OC07_内存管理
//
//  Created by dllo on 15/12/9.
//  Copyright © 2015年 dllo. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
    
        
        
        
# pragma mark - 知识点1 影响内存引用计数的方法
    
    /**
     * 增加 : alloc, retain, copy
     * 减少 : release, autorelease
     
     * 查看引用计数方法 : returnCount  切记,此方法不要在工程中调用, 因为显示的结果有时是错误的.
     */
#if 0
    Person *per1 = [[Person alloc]init];
    NSLog(@"%ld",[per1 retainCount]);
    [per1 retain];
    NSLog(@"%ld",[per1 retainCount]);
    [per1 release];
    NSLog(@"%ld",[per1 retainCount]);
    [per1 release];
    NSLog(@"%ld",[per1 retainCount]);/** 注意: 此时per1 的引用计数应该是0,但是retainCount方法显示的是1, 所以说此方法有时显示不准确 */
        
    Person *per2 = [[Person alloc]init];
    [per2 retain];/** 计数:2*/
    @autoreleasepool {
        
        [per2 autorelease];/** 此时不立即减1,出了自动释放池之后计数才减1 */
        NSLog(@"%ld",[per2 retainCount]);
    }
    NSLog(@"%ld",[per2 retainCount]);
    
#endif
        
# pragma mark - 知识点2 属性的内存管理
    
        /**
         * 属性的内存管理主要是setter方法的内部实现细节
         * 详见Person类的_name的setter方法, _age的setter方法
         
         * 总结: setter方法的具体实现,不用开发者编写,属性自动实现. 系统会采用哪种setter实现方式呢?  由定义属性时的语义字段决定(assign,retain,copy)
         */
        
# pragma mark - 知识点3 重写dealloc方法
    
    
    /** 为什么要重写
     *    因为对象类型的实例变量(_name....),它的setter方法会引起引用计数多1, 所以要在适当的时候,将引用计数-1,  适当的时候就是在整个对象(per1)释放之前.  所以重写
     详见Person类
     */
    
        
# pragma mark - 知识点4 getter方法实现
    
    /** 
     * 详见Person的_name的getter方法.
     
     注意 当同时编写属性的setter和getter方法时,系统会提示实例变量不识别.  解决方法: 加上@synthsize 属性 = _属性名
     */
    
#pragma mark - 知识点5 便利构造器的内存问题
    
        
        /** 详见Person类 */
        
# pragma mark - 知识点6 init方法内部实例变量的写法
    
    /** 详见Person类 */
    
# pragma mark - 知识点7 KVC(key - Value - Coding)  报错????
    /** 创建一个类: Student,父类:NSObject
     * 只声明实例变量不声明属性,没有setter getter方法
     */
    
    Student *stu1 = [[Student alloc]init];
    /** 对实例变量进行访问 使用KVC实现实例变量的访问*/
    [stu1 setValue:@"Tom" forKey:@"name"];
    [stu1 setValue:@20 forKey:@"age"];
    [stu1 setValue:@"male" forKey:@"sex"];
    /** 使用KVC取值 */
    NSLog(@"name:%@",[stu1 valueForKey:@"name"]);
    NSLog(@"age:%@",[stu1 valueForKey:@"age"]);
    NSLog(@"sex:%@",[stu1 valueForKey:@"sex"]);
    
    
    
    Student *stu2 = [[Student alloc]init];
    
    NSDictionary *dic = @{@"name":@"zhangsan",
                          @"age":@"20",
                          @"sex":@"male"};
    /*使用KVC将字典中的值同时赋给对象的(多个)实例变量,*/
    [stu2 setValuesForKeysWithDictionary:dic];
    NSLog(@"%@",[stu2 valueForKey:@"name"]);
    NSLog(@"%@",[stu2 valueForKey:@"sex"]);
    
    
    
    
   
    return 0;
}
